package com.inifitness.tenant.core.config.mp.handler;

import java.lang.reflect.Method;

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.inifitness.common.basic.BaseEnum;
import com.inifitness.common.enums.DataScopeEnum;
import com.inifitness.tenant.core.config.mp.annotation.DataPermission;
import com.inifitness.tenant.core.security.util.SecurityUtils;

import cn.hutool.core.text.CharSequenceUtil;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;

/**
 * 数据权限控制器
 *
 * @author sunjinfeng
 * @since 2024/04/18 11:00:00
 */
@Log4j2
public class MyDataPermissionHandler implements DataPermissionHandler {

  @Override
  @SneakyThrows
  public Expression getSqlSegment(Expression where, String mappedStatementId) {

    Class<?> clazz = Class.forName(
        mappedStatementId.substring(0, mappedStatementId.lastIndexOf(StringPool.DOT)));
    String methodName = mappedStatementId.substring(
        mappedStatementId.lastIndexOf(StringPool.DOT) + 1);
    Method[] methods = clazz.getDeclaredMethods();
    for (Method method : methods) {
      DataPermission annotation = method.getAnnotation(DataPermission.class);
      // 如果没有注解或者是超级管理员，直接返回
      if (annotation == null || SecurityUtils.isRoot()) {
        return where;
      }
      if (method.getName().equals(methodName) || (method.getName() + "_COUNT").equals(methodName)) {
        return dataScopeFilter(annotation.deptAlias(), annotation.deptIdColumnName(),
            annotation.userAlias(), annotation.userIdColumnName(), where);
      }
    }
    return where;
  }

  /**
   * 构建过滤条件
   *
   * @param where 当前查询条件
   * @return 构建后查询条件
   */
  @SneakyThrows
  public static Expression dataScopeFilter(String orgAlias, String orgIdColumnName,
      String userAlias, String userIdColumnName, Expression where) {

    String orgColumnName =
        CharSequenceUtil.isNotBlank(orgAlias) ? (orgAlias + StringPool.DOT + orgIdColumnName)
            : orgIdColumnName;
    String userColumnName =
        CharSequenceUtil.isNotBlank(userAlias) ? (userAlias + StringPool.DOT + userIdColumnName)
            : userIdColumnName;

    // 获取当前用户的数据权限
    Integer dataScope = SecurityUtils.getDataScope();

    DataScopeEnum dataScopeEnum = BaseEnum.getEnumByValue(DataScopeEnum.class, dataScope);

    Long orgId;
    Long userId;
    String appendSqlStr;
    switch (dataScopeEnum) {
      case ALL:
        return where;
      case DEPT:
        orgId = SecurityUtils.getDeptId();
        appendSqlStr = orgColumnName + StringPool.EQUALS + orgId;
        break;
      case SELF:
        userId = SecurityUtils.getUserId();
        appendSqlStr = userColumnName + StringPool.EQUALS + userId;
        break;
      // 默认部门及子部门数据权限
      default:
        orgId = SecurityUtils.getDeptId();
        appendSqlStr = orgColumnName + " IN ( SELECT id FROM sys_dept WHERE id = " + orgId
            + " OR FIND_IN_SET( " + orgId + " , tree_path ) )";
        break;
    }

    if (CharSequenceUtil.isBlank(appendSqlStr)) {
      return where;
    }

    Expression appendExpression = CCJSqlParserUtil.parseCondExpression(appendSqlStr);

    if (where == null) {
      return appendExpression;
    }

    return new AndExpression(where, appendExpression);
  }
}

